//
//  DefaultTableViewCell.swift
//  SwiftHub
//
//  Created by Khoren Markosyan on 6/30/18.
//  Copyright © 2018 Khoren Markosyan. All rights reserved.
//

import UIKit

class DefaultTableViewCell: TableViewCell {

    lazy var leftImageView: ImageView = {
        let view = ImageView(frame: CGRect())
        view.contentMode = .scaleAspectFit
        view.layerCornerRadius = 25
        view.snp.makeConstraints({ (make) in
            make.size.equalTo(50)
        })
        return view
    }()

    lazy var badgeImageView: ImageView = {
        let view = ImageView(frame: CGRect())
        view.backgroundColor = .white
        view.layerCornerRadius = 10
        view.layerBorderColor = .white
        view.layerBorderWidth = 1
        containerView.addSubview(view)
        view.snp.makeConstraints({ (make) in
            make.bottom.left.equalTo(self.leftImageView)
            make.size.equalTo(20)
        })
        return view
    }()

    lazy var titleLabel: Label = {
        let view = Label()
        view.font = view.font.withSize(14)
        return view
    }()

    lazy var detailLabel: Label = {
        let view = Label()
        view.font = view.font.withSize(12)
        view.setPriority(UILayoutPriority.defaultLow, for: NSLayoutConstraint.Axis.vertical)
        return view
    }()

    lazy var secondDetailLabel: Label = {
        let view = Label()
        view.font = view.font.bold.withSize(11)
        return view
    }()

    lazy var attributedDetailLabel: Label = {
        let view = Label()
        view.font = view.font.bold.withSize(11)
        return view
    }()

    lazy var textsStackView: StackView = {
        let views: [UIView] = [self.titleLabel, self.detailLabel, self.secondDetailLabel, self.attributedDetailLabel]
        let view = StackView(arrangedSubviews: views)
        view.spacing = 2
        return view
    }()

    lazy var rightImageView: ImageView = {
        let view = ImageView(frame: CGRect())
        view.image = R.image.icon_cell_disclosure()?.template
        view.snp.makeConstraints({ (make) in
            make.width.equalTo(20)
        })
        return view
    }()

    override func makeUI() {
        super.makeUI()

        titleLabel.theme.textColor = themeService.attribute { $0.text }
        detailLabel.theme.textColor = themeService.attribute { $0.textGray }
        secondDetailLabel.theme.textColor = themeService.attribute { $0.text }
        leftImageView.theme.tintColor = themeService.attribute { $0.secondary }
        rightImageView.theme.tintColor = themeService.attribute { $0.secondary }

        stackView.addArrangedSubview(leftImageView)
        stackView.addArrangedSubview(textsStackView)
        stackView.addArrangedSubview(rightImageView)
        stackView.snp.remakeConstraints({ (make) in
            let inset = self.inset
            make.edges.equalToSuperview().inset(UIEdgeInsets(top: inset/2, left: inset, bottom: inset/2, right: inset))
            make.height.greaterThanOrEqualTo(Configs.BaseDimensions.tableRowHeight)
        })
    }

    override func bind(to viewModel: TableViewCellViewModel) {
        super.bind(to: viewModel)
        guard let viewModel = viewModel as? DefaultTableViewCellViewModel else { return }

//        #<总结>: 使用RxSwift设置viewModel的title为titleLabel的文本。
//
//        #<分析>:
//
//        1. **viewModel.title.asDriver()**: 这里，我们从一个`viewModel`对象中获取`title`属性，并调用`asDriver()`方法将其转换为`Driver<String?>`类型（假设`title`是字符串类型）。在RxSwift中，`Driver`是一种特殊的Observable，它总是发出在主线程上的值，并且保证在序列结束时（无论是正常结束还是错误）都会调用`dispose`方法。
//        2. **drive(titleLabel.rx.text)**: `drive`方法是`Driver`类型特有的，它接受一个`ObserverType`参数（在这里是`titleLabel.rx.text`），表示当`Driver`发出新值时，应该将这个值设置给`titleLabel`的`text`属性。
//        3. **disposed(by: rx.disposeBag)**: 当不再需要监听这个`Driver`时，我们需要调用其`dispose`方法来避免内存泄漏。这里，我们使用`rx.disposeBag`来管理所有需要`dispose`的对象。当你把某个对象添加到`disposeBag`中时，一旦`disposeBag`被`dispose`（通常在视图控制器的`deinit`方法中），所有添加进去的对象都会被自动`dispose`。
//
//        **注意**：为了使代码更加清晰，你可以考虑将`rx.disposeBag`设置为视图控制器的一个属性，并在视图控制器的`deinit`方法中显式调用其`dispose`方法。这样做的好处是，当视图控制器被释放时，所有与之相关的RxSwift订阅都会被自动清理。
        
        viewModel.title.asDriver().drive(titleLabel.rx.text).disposed(by: rx.disposeBag)
        
//        #<总结>: 更新`titleLabel`的隐藏状态，基于`viewModel.title`是否为空字符串。
//
//        #<分析>:
//        1. `viewModel.title.asDriver()`: 将`viewModel.title`（可能是一个`Observable<String?>`类型）转换为`Driver<String?>`。Driver是RxSwift中一种特殊的Observable，它总是发送在主线程上的值，并且会自动处理错误和完成通知。
//
//        2. `.replaceNilWith("")`: 如果Driver发出的值是nil，则将其替换为空字符串("")。
//
//        3. `.map { $0.isEmpty }`: 映射操作，检查每个字符串是否为空。如果字符串为空，则返回true，否则返回false。
//
//        4. `.drive(titleLabel.rx.isHidden)`: 使用上述得到的布尔值（是否为空字符串）来驱动`titleLabel`的`isHidden`属性。如果为true（即字符串为空），则隐藏`titleLabel`；如果为false，则显示`titleLabel`。
//
//        5. `.disposed(by: rx.disposeBag)`: 将上述整个链式操作添加到`disposeBag`中，以便在适当的时候（如视图控制器被释放时）自动取消订阅并释放资源。
//
//        6. 排版优化：上述代码链式调用清晰明了，没有多余的变量或中间步骤，直接通过流的方式完成了从数据源到UI的绑定。
        viewModel.title.asDriver().replaceNilWith("").map { $0.isEmpty }.drive(titleLabel.rx.isHidden).disposed(by: rx.disposeBag)

        viewModel.detail.asDriver().drive(detailLabel.rx.text).disposed(by: rx.disposeBag)
        viewModel.detail.asDriver().replaceNilWith("").map { $0.isEmpty }.drive(detailLabel.rx.isHidden).disposed(by: rx.disposeBag)

        viewModel.secondDetail.asDriver().drive(secondDetailLabel.rx.text).disposed(by: rx.disposeBag)
        viewModel.secondDetail.asDriver().replaceNilWith("").map { $0.isEmpty }.drive(secondDetailLabel.rx.isHidden).disposed(by: rx.disposeBag)

        viewModel.attributedDetail.asDriver().drive(attributedDetailLabel.rx.attributedText).disposed(by: rx.disposeBag)
        viewModel.attributedDetail.asDriver().map { $0 == nil }.drive(attributedDetailLabel.rx.isHidden).disposed(by: rx.disposeBag)

        viewModel.badge.asDriver().drive(badgeImageView.rx.image).disposed(by: rx.disposeBag)
        viewModel.badge.map { $0 == nil }.asDriver(onErrorJustReturn: true).drive(badgeImageView.rx.isHidden).disposed(by: rx.disposeBag)

        viewModel.badgeColor.asDriver().drive(badgeImageView.rx.tintColor).disposed(by: rx.disposeBag)

        viewModel.hidesDisclosure.asDriver().drive(rightImageView.rx.isHidden).disposed(by: rx.disposeBag)

        viewModel.image.asDriver().filterNil()
            .drive(leftImageView.rx.image).disposed(by: rx.disposeBag)

        viewModel.imageUrl.map { $0?.url }.asDriver(onErrorJustReturn: nil).filterNil()
            .drive(leftImageView.rx.imageURL).disposed(by: rx.disposeBag)

        
//        #<总结>:
//        闭包中的`in`关键字用于分隔闭包参数和闭包体，表示闭包参数列表的结束和闭包体的开始。
//
//        #<分析>:
//        在Swift中，闭包（Closure）是一种特殊的代码块，它可以捕获并存储其所在上下文中定义的常量和变量的引用。闭包通常用于函数式编程中，以传递代码块作为参数或返回值。
//
//        在闭包的定义中，`in`关键字起到了分隔的作用。它前面是闭包的参数列表（如果有的话），后面是闭包的主体（即闭包要执行的代码）。`in`关键字并不是必须的，但是当闭包有多个参数或者需要显式指出闭包体的开始时，它通常会提高代码的可读性。
//
//        例如，在您的示例代码中：
//
//        ```swift
//        .drive(onNext: { [weak self] (url) in
//            self?.leftImageView.hero.id = url
//        })
//        ```
//
//        这里定义了一个闭包，它接受一个参数`url`，并且使用了`[weak self]`来避免循环引用。`in`关键字后面是闭包的主体，即`self?.leftImageView.hero.id = url`这行代码。
//
//        如果没有`in`关键字，Swift编译器可能会无法正确区分闭包的参数列表和闭包体，导致编译错误。因此，`in`关键字在这里起到了明确分隔和指示的作用。
        viewModel.imageUrl.asDriver().filterNil()
            .drive(onNext: { [weak self] (url) in
                self?.leftImageView.hero.id = url
                
            }).disposed(by: rx.disposeBag)
        
        
        
//        // 声明一个带两个入参的匿名函数
//        let anonymousFunction:(Int,Int) -> Int = {
//            (p1,p2) in return p1+p2
//        }
//        
//        //更简洁的写法 在这个例子中，`$0` 和 `$1` 分别代表了第一个和第二个参数。当参数的类型在上下文中已经明确时，你可以使用这种更简洁的语法。
//        let anonymousFunctionNew:(Int,Int) -> Int = {$0+$1}

    }
}
